// Copyright (c) Razanii 2022
// License: GNU LGPLv3. More info in root project directory file 'LICENSE'

#pragma once

#include <string>
#include <regex>
#include <map>



namespace convertum::data {

const std::map<char, unsigned long int> TYPES = {
	// bit		byte
	{'b', 1}, {'B', 8},

	//	 SI
	// kilo	10^3
	{'k', 1000},
	// mega	10^6
	{'m', 1000000},
	// giga	10^9
	{'g', 1000000000},
	// tera	10^12
	{'t', 1000000000000},
	// peta	10^15
	{'p', 1000000000000000},
	// exa	10^18
	{'e', 1000000000000000000},

	//  IEC
	// kibi	2^10
	{'K', 1024},
	// mebi	2^20
	{'M', 1048576},
	// gibi	2^30
	{'G', 1073741824},
	// tebi	2^40
	{'T', 1099511627776},
	// pebi	2^50
	{'P', 1125899906842624},
	// exbi	2^60
	{'E', 1152921504606846976}

	// This is not a complete list. (zetta|zebi, yotta|yobi ...)
	// The sequel is missing due to memory overflow.
};

bool check_type(const std::string& TYPE);

template<typename T>
T convert(T size, const std::string& FROM, const std::string& TO) {
	 if (!convertum::data::check_type(FROM))
		  throw std::invalid_argument("Second argument 'FROM' type is not correct");
	 if (!convertum::data::check_type(TO))
		  throw std::invalid_argument("Third argument 'FROM' type is not correct");

	 // Convert to bits
	 for (const auto& i : FROM) {
		 if (i == 'i') continue;
		  size = size * TYPES.at(i);
	 }

	 // Convert to output format (TO)
	 for (const auto& i : TO) {
		 if (i == 'i') continue;
		  size = size / TYPES.at(i);
	 }

	 return size;
}

}
